package service

import (
	"fmt"
	"github.com/vueadmin/app/admin/internal/dto"
	"github.com/vueadmin/app/admin/internal/model"
	"github.com/vueadmin/app/admin/internal/svc"
	"github.com/vueadmin/utils/conv"
	"strings"
)

type BaseService struct {
	svcCtx *svc.ServiceContext
}

func NewBaseService(svcCtx *svc.ServiceContext) *BaseService {
	return &BaseService{
		svcCtx: svcCtx,
	}
}

// 获取当前角色的左侧菜单
func (p BaseService) GetMenu(role_id uint, access []string) []*model.Menu {
	var data []*model.Menu
	if role_id == 1 {
		data = p.getBaseMenus()
	} else {
		data = p.getMyMenu(access, p.getBaseMenus())
	}
	return data
}

// 获取非超级管理员的菜单
func (p BaseService) getMyMenu(access []string, data []*model.Menu) []*model.Menu {
	var roleMenu []*model.Menu
	for _, v := range data {
		if conv.IsValueInList(v.Access, access) {
			roleMenu = append(roleMenu, &model.Menu{
				Title:          v.Title,
				Icon:           v.Icon,
				Url:            v.Url,
				Pid:            v.Pid,
				Access:         v.Access,
				MenuId:         v.MenuId,
				ComponentPath:  v.ComponentPath,
				Path:           v.Path,
				ControllerName: v.ControllerName,
				Children:       p.getMyMenu(access, v.Children),
			})
		}
	}
	return roleMenu
}

// 获取左侧菜单
func (p BaseService) getBaseMenus() []*model.Menu {
	var data []*model.Menu
	filed := "menu_id,pid,title,controller_name,component_path,status,icon,sortid,url"
	if err := p.svcCtx.Db.Model(&model.Menu{}).Select(filed).Where("app_id", 1).Where("status", 1).Order("sortid asc").Find(&data).Error; err != nil {
		panic(err)
	}
	for _, val := range data {
		if val.Icon == "" {
			val.Icon = "el-icon-menu"
		}
		if val.Url == "" {
			val.Path = fmt.Sprintf("/admin/%s/index", val.ControllerName)
			val.Access = fmt.Sprintf("/admin/%s", val.ControllerName)
		} else {
			val.Path = val.Url
			val.Access = val.Url
		}
	}

	return p.getTreeMenu(data, 0)
}

func (p BaseService) getTreeMenu(list []*model.Menu, parentId int) []*model.Menu {
	res := make([]*model.Menu, 0)
	for _, v := range list {
		if int(v.Pid) == parentId {
			v.Children = p.getTreeMenu(list, int(v.MenuId))
			res = append(res, v)
		}
	}
	return res
}

// 获取需要渲染的组件
func (p BaseService) GetComponents(role_id uint, menu []*model.Menu) []map[string]interface{} {
	components := p.getBaseComponents(menu)
	if role_id == 1 {
		components = append(components,
			map[string]interface{}{"name": "Field", "path": "/admin/Field/index", "meta": map[string]interface{}{"title": "字段管理"}, "component_path": "admin/sys/field/Index.vue"},
			map[string]interface{}{"name": "Action", "path": "/admin/Action/index", "meta": map[string]interface{}{"title": "方法管理"}, "component_path": "admin/sys/action/Index.vue"},
		)
	}
	return components
}

// 获取隐藏菜单组件
func (p BaseService) GetHiddenComponents(role_id uint, access []string) []map[string]interface{} {
	var (
		data       []*model.Menu
		components []map[string]interface{}
	)
	p.svcCtx.Db.Model(&model.Menu{}).Where("status = 0").Where("component_path is not null").Find(&data)
	for _, v := range data {
		if role_id == 1 || conv.IsValueInList(v.ControllerName, access) {
			components = append(components, map[string]interface{}{
				"name":           v.ControllerName,
				"path":           fmt.Sprintf("/admin/%s/index", v.ControllerName),
				"component_path": v.ComponentPath,
				"meta": map[string]interface{}{
					"title": v.Title,
				},
			})
		}
	}
	return components
}

func (p BaseService) getBaseComponents(menu []*model.Menu) []map[string]interface{} {
	param := make([]map[string]interface{}, 0)
	for _, val := range menu {
		param = append(param, map[string]interface{}{
			"name":           val.ControllerName,
			"path":           val.Path,
			"component_path": val.ComponentPath,
			"meta":           map[string]interface{}{"title": val.Title},
		})
		if len(val.Children) > 0 {
			tmp := p.getBaseComponents(val.Children)
			for _, v := range tmp {
				param = append(param, map[string]interface{}{
					"name":           v["name"],
					"path":           v["path"],
					"component_path": v["component_path"],
					"meta":           map[string]interface{}{"title": v["meta"].(map[string]interface{})["title"]},
				})
			}
		}
	}
	return param
}

func (p BaseService) GetRoleMenu() ([]*model.Menu, error) {
	data, err := p.getNodes(0)
	return data, err
}

func (p BaseService) getNodes(pid int) ([]*model.Menu, error) {
	var data []*model.Menu
	filed := "menu_id,pid,title,controller_name,status,icon,sortid,url"
	if err := p.svcCtx.Db.Model(&model.Menu{}).Select(filed).Where("pid", pid).Where("app_id", 1).Where("status", 1).Order("sortid asc").Find(&data).Error; err != nil {
		return nil, err
	}
	for _, v := range data {
		if v.Url != "" {
			v.Access = v.Url
			v.Title = fmt.Sprintf("%s(%s)", v.Title, v.Url)
		} else {
			v.Access = fmt.Sprintf("/admin/%s", v.ControllerName)
			v.Title = fmt.Sprintf("%s(/admin/%s)", v.Title, v.ControllerName)
		}
		var subcount int64
		p.svcCtx.Db.Model(&model.Menu{}).Select(filed).Where("pid", v.MenuId).Where("status", 1).Count(&subcount)
		if subcount > 0 {
			if len(p.getFunc(v)) > 0 {
				funs := p.getFunc(v)
				menus, _ := p.getNodes(conv.Int(v.MenuId))
				for _, val := range menus {
					funs = append(funs, val)
				}
				v.Children = funs
			} else {
				v.Children, _ = p.getNodes(conv.Int(v.MenuId))
			}
		} else {
			v.Children = p.getFunc(v)
		}
	}
	return data, nil
}

// 获取方法节点
func (p BaseService) getFunc(info *model.Menu) []*model.Menu {
	var (
		data   []*model.Menu
		action []map[string]interface{}
	)
	p.svcCtx.Db.Table("cd_action").Select("name,type,action_name").Where("menu_id = ?", info.MenuId).Order("sortid asc").Find(&action)
	for _, v := range action {
		if conv.Int(v["type"]) == 3 {
			action = append(action, map[string]interface{}{
				"name":        fmt.Sprintf("%s详情", conv.String(v["name"])),
				"action_name": fmt.Sprintf("get%sInfo", strings.Title(conv.String(v["action_name"]))),
			})
		}
	}
	for _, v := range action {
		data = append(data, &model.Menu{
			Title:  fmt.Sprintf("%s(admin/%s/%s)", conv.String(v["name"]), info.ControllerName, conv.String(v["action_name"])),
			Access: fmt.Sprintf("/admin/%s/%s", info.ControllerName, conv.String(v["action_name"])),
		})
	}
	return data
}

// 修改密码
func (p BaseService) ResetPwd(req *dto.ResetPwdReq, user_id interface{}) error {
	return p.svcCtx.Db.Model(&model.Adminuser{}).Where("user_id = ?", user_id).Update("pwd", conv.EncryptPassword(req.Password)).Error
}

type homeMenu struct {
	Title          string `json:"title"`
	MenuPic        string `json:"menu_pic"`
	ControllerName string `json:"controller_name"`
	Url            string `json:"url"`
}

// 获取首页快捷菜单
func (p BaseService) GetHomeMenu() []*homeMenu {
	var list []*homeMenu
	p.svcCtx.Db.Model(&model.Menu{}).Where("app_id", 1).Where("home_show = ?", 1).Find(&list)
	for _, v := range list {
		if v.Url == "" {
			v.Url = fmt.Sprintf("/admin/%s/index", v.ControllerName)
		}
	}
	return list
}
